#include "epollsrv.h"

#define __MAX_BUFFER 4096

using namespace std;

std::auto_ptr<CepollSrv> CepollSrv::sm_inst;

CepollSrv::CepollSrv()
{

}

CepollSrv::~CepollSrv()
{
    close(m_iSock);
}

CepollSrv *CepollSrv::Instance()
{
    if(nullptr == sm_inst.get())
        sm_inst=std::auto_ptr<CepollSrv> (new CepollSrv);
    return sm_inst.get();
}


bool CepollSrv::InitServer(const char *szIp, int iPort)
{
    //创建epoll
    m_iEpollFd=epoll_create(__MAX_SOCKFD_COUNT);

    //设置非阻塞模式
  //  int opts = O_NONBLOCK;
    if(0 > fcntl(m_iEpollFd,F_SETFL,O_NONBLOCK))
    {
        cout<<"设置非阻塞模式失败！\n";
        return false;
    }

    //创建套接字
    m_iSock=socket(AF_INET,SOCK_STREAM,0);
    if(0 > m_iSock)
    {
        cout<<"socket error! \n";
        return false;
    }

    m_listenAddr.sin_family=AF_INET;
    m_listenAddr.sin_port=htons(iPort);
    m_listenAddr.sin_addr.s_addr=inet_addr(szIp);
    m_listenAddr.sin_addr.s_addr=htonl(INADDR_ANY);  //test use

    int iReuseaddr_on = 1;   //支持端口复用
    setsockopt(m_iSock,SOL_SOCKET,SO_REUSEADDR,&iReuseaddr_on,sizeof(iReuseaddr_on) );

    //绑定
    if( 0 != bind(m_iSock,(sockaddr*)&m_listenAddr,sizeof(m_listenAddr)) )
    {
        cout<<"bind error! ---"<< strerror(errno)<<endl;
        return false;
    }

    //监听
    if(0 > listen(m_iSock,20))
    {
       cout<<"listen error! \n";
       return false;
    }

    //监听线程，此线程负责接收客户端连接，加入epoll中
    if(pthread_create(&m_ListenThreadId,0,/*(void* (*)  (void*))*/ListenThread,this))
    {
        cout<<"Server 监听线程创建失败！！！ \n";
        return false;
    }
    else
    {
        cout<<"服务器监听中.....\n";
    }
    return true;
}

void* CepollSrv::ListenThread(void *lpVoid)
{
    CepollSrv* pThis = (CepollSrv*)lpVoid;
    sockaddr_in remote_addr;
    socklen_t len = sizeof(remote_addr);

    while(true)
    {
        int iClient_socket = accept(pThis->m_iSock,(sockaddr*)&remote_addr,&len);
        if(0> iClient_socket)
        {
            cout<<"Server Accept failed! client_socket: "<<iClient_socket<<", reason is:  "
               <<strerror(errno)<<", erron is: "<<errno<<endl;
            continue;
        }
        else
        {  //向epoll中添加连接的客户端
            struct epoll_event ev;
            ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
            ev.data.fd = iClient_socket;   //记录socket句柄
            epoll_ctl(pThis->m_iEpollFd, EPOLL_CTL_ADD, iClient_socket,&ev);
        }
    }

    return nullptr;
}

void CepollSrv::Run()
{
    while (true)
    {
        struct epoll_event events[__MAX_SOCKFD_COUNT];
        int nfds = epoll_wait(m_iEpollFd,events,__MAX_SOCKFD_COUNT,-1);

        char buffer[__MAX_BUFFER];  // 接收数据的buffer
        for(int i = 0; i< nfds; i++)
        {
            int iClient_socket = events[i].data.fd;
            memset(buffer,0,__MAX_BUFFER );
            if(events[i].events & EPOLLIN)         //监听到读事件
            {
                int rev_size = recv(events[i].data.fd,buffer, __MAX_BUFFER,0);
                if(0 >= rev_size)
                {
                    cout<<"recv error: recv size: "<<rev_size << endl;
                    struct epoll_event event_del;
                    event_del.data.fd = events[i].data.fd;
                    event_del.events = 0;

                    epoll_ctl(m_iEpollFd,EPOLL_CTL_DEL, event_del.data.fd,&event_del);
                    close(event_del.data.fd);
                }
                else
                {
                    cout<<"Terminal Received Msg Content: "<<buffer << endl;
                    struct epoll_event ev;
                    ev.data.fd = iClient_socket;   //记录socket句柄
                    ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;

                    sprintf(buffer,"我娜----\r\n");
                    send(iClient_socket,buffer,strlen(buffer),MSG_NOSIGNAL);

                    epoll_ctl(m_iEpollFd,EPOLL_CTL_MOD, iClient_socket,&ev);
                }
            }
            else if(events[i].events & EPOLLOUT)  //监听到写事件，发送数据
            {
                sprintf(buffer,"Hello, Client fd: %d\n",iClient_socket);

                int sendSize = send(iClient_socket,buffer,strlen(buffer) + 1,MSG_NOSIGNAL);
                if(0 >= sendSize)
                {
                    struct epoll_event event_del;
                    event_del.data.fd = events[i].data.fd;
                    event_del.events = 0;

                    epoll_ctl(m_iEpollFd,EPOLL_CTL_DEL,event_del.data.fd,&event_del);
                }
                else
                {
                    cout<<"Server reply msg ok! buffer: "<<buffer<<endl;
                    struct epoll_event ev;
                    ev.data.fd = iClient_socket;    //记录socket句柄
                    ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;

                    epoll_ctl(m_iEpollFd,EPOLL_CTL_MOD,iClient_socket,&ev);
                }
            }
            else
            {
                cout<<"EPOLL ERROR\n"<<endl;
                epoll_ctl(m_iEpollFd,EPOLL_CTL_DEL,events[i].data.fd,&events[i]);
            }
        }
    }
}